package com.seadragon.app.ksr.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import com.seadragon.app.ksr.dao.CategoryDao;
import com.seadragon.app.ksr.dao.StateLookUpDao;
import com.seadragon.app.ksr.model.Category;
import com.seadragon.app.ksr.model.tiger.StateLookUp;

@Service("cacheManager")
@Scope("singleton")
public class CacheManager {
	@Autowired
	private CategoryDao categoryDao;

	@Autowired
	private StateLookUpDao stateLookUpDao;

	private Object stateLock = new Object();

	private Object categoryLock = new Object();

	private Object countyLock = new Object();

	private Object zipLock = new Object();

	private Map<String, Category> categoryMap;

	private List<Category> leafCategories;

	private Map<String, String> secondaryUnitDesignatorMap;

	private Map<String, String> stateFipsToNameMap;

	private Map<String, String> stateNameToFipsMap;
	/**
	 * Unstandardized street Pre Street Suffix Post NORTHEAST 1ST WAY NE 1st Way
	 * NORTH MAIN ST EAST N Main St E
	 */
	private Map<String, String> streetAbbreviationMap;

	private Map<String, String> streetDirectionMap;

	public CacheManager(){
	}
	
	public void init() {
		secondaryUnitDesignatorMap = new HashMap<String, String>();
		secondaryUnitDesignatorMap.put("Apartment", "APT");
		secondaryUnitDesignatorMap.put("Basement", "BSMT");
		secondaryUnitDesignatorMap.put("Building", "BLDG");
		secondaryUnitDesignatorMap.put("Department", "DEPT");
		secondaryUnitDesignatorMap.put("Floor", "FL");
		secondaryUnitDesignatorMap.put("Front", "FRNT");
		secondaryUnitDesignatorMap.put("Hanger", "HNGR");
		secondaryUnitDesignatorMap.put("Key", "KEY");
		secondaryUnitDesignatorMap.put("Lobby", "LBBY");
		secondaryUnitDesignatorMap.put("Lot", "LOT");
		secondaryUnitDesignatorMap.put("Lower", "LOWR");
		secondaryUnitDesignatorMap.put("Office", "OFC");
		secondaryUnitDesignatorMap.put("Penthouse", "PH");
		secondaryUnitDesignatorMap.put("Pier", "PIER");
		secondaryUnitDesignatorMap.put("Rear", "REAR");
		secondaryUnitDesignatorMap.put("Room", "RM");
		secondaryUnitDesignatorMap.put("Side", "SIDE");
		secondaryUnitDesignatorMap.put("Slip", "SLIP");
		secondaryUnitDesignatorMap.put("Space", "SPC");
		secondaryUnitDesignatorMap.put("Stop", "STOP");
		secondaryUnitDesignatorMap.put("Suite", "STE");
		secondaryUnitDesignatorMap.put("Trailer", "TRLR");
		secondaryUnitDesignatorMap.put("Unit", "UNIT");
		secondaryUnitDesignatorMap.put("Upper", "UPPR");

		streetAbbreviationMap = new HashMap<String, String>();
		streetAbbreviationMap.put("ALLEY", "ALY");
		streetAbbreviationMap.put("ALLEE", "ALY");
		streetAbbreviationMap.put("ALLEY", "ALY");
		streetAbbreviationMap.put("ALLY", "ALY");
		streetAbbreviationMap.put("ANEX", "ANX");
		streetAbbreviationMap.put("ANNEX", "ANX");
		streetAbbreviationMap.put("ANNX", "ANX");
		streetAbbreviationMap.put("ARCADE", "ARC");
		streetAbbreviationMap.put("AVENUE", "AVE");
		streetAbbreviationMap.put("AV", "AVE");
		streetAbbreviationMap.put("AVEN", "AVE");
		streetAbbreviationMap.put("AVENU", "AVE");
		streetAbbreviationMap.put("AVENUE", "AVE");
		streetAbbreviationMap.put("AVN", "AVE");
		streetAbbreviationMap.put("AVNUE", "AVE");
		streetAbbreviationMap.put("BAYOU", "BYU");
		streetAbbreviationMap.put("BAYOO", "BYU");
		streetAbbreviationMap.put("BEACH", "BCH");
		streetAbbreviationMap.put("BEACH", "BCH");
		streetAbbreviationMap.put("BEND", "BND");
		streetAbbreviationMap.put("BLUFF", "BLF");
		streetAbbreviationMap.put("BLUF", "BLF");
		streetAbbreviationMap.put("BLUFFS", "BLFS");
		streetAbbreviationMap.put("BOTTOM", "BTM");
		streetAbbreviationMap.put("BOT", "BTM");
		streetAbbreviationMap.put("BOTTM", "BTM");
		streetAbbreviationMap.put("BOTTOM", "BTM");
		streetAbbreviationMap.put("BOULEVARD", "BLVD");
		streetAbbreviationMap.put("BOUL", "BLVD");
		streetAbbreviationMap.put("BOULV", "BLVD");
		streetAbbreviationMap.put("BRANCH", "BR");
		streetAbbreviationMap.put("BRNCH", "BR");
		streetAbbreviationMap.put("BRIDGE", "BRG");
		streetAbbreviationMap.put("BROOK", "BRK");
		streetAbbreviationMap.put("BROOKS", "BRKS");
		streetAbbreviationMap.put("BURG", "BG");
		streetAbbreviationMap.put("BURGS", "BGS");
		streetAbbreviationMap.put("BYPASS", "BYP");
		streetAbbreviationMap.put("BYPA", "BYP");
		streetAbbreviationMap.put("BYPAS", "BYP");
		streetAbbreviationMap.put("BYPASS", "BYP");
		streetAbbreviationMap.put("BYPS", "BYP");
		streetAbbreviationMap.put("CAMP", "CP");
		streetAbbreviationMap.put("CMP", "CP");
		streetAbbreviationMap.put("CANYON", "CYN");
		streetAbbreviationMap.put("CANYN", "CYN");
		streetAbbreviationMap.put("CNYN", "CYN");
		streetAbbreviationMap.put("CAPE", "CPE");
		streetAbbreviationMap.put("CAUSEWAY", "CSWY");
		streetAbbreviationMap.put("CAUSWA", "CSWY");
		streetAbbreviationMap.put("CENTER", "CTR");
		streetAbbreviationMap.put("CEN", "CTR");
		streetAbbreviationMap.put("CENT", "CTR");
		streetAbbreviationMap.put("CENTER", "CTR");
		streetAbbreviationMap.put("CENTR", "CTR");
		streetAbbreviationMap.put("CENTRE", "CTR");
		streetAbbreviationMap.put("CNTER", "CTR");
		streetAbbreviationMap.put("CNTR", "CTR");
		streetAbbreviationMap.put("CENTERS", "CTRS");
		streetAbbreviationMap.put("CIRCLE", "CIR");
		streetAbbreviationMap.put("CIRC", "CIR");
		streetAbbreviationMap.put("CIRCL", "CIR");
		streetAbbreviationMap.put("CIRCLE", "CIR");
		streetAbbreviationMap.put("CRCL", "CIR");
		streetAbbreviationMap.put("CRCLE", "CIR");
		streetAbbreviationMap.put("CIRCLES", "CIRS");
		streetAbbreviationMap.put("CLIFF", "CLF");
		streetAbbreviationMap.put("CLIFFS", "CLFS");
		streetAbbreviationMap.put("CLUB", "CLB");
		streetAbbreviationMap.put("COMMON", "CMN");
		streetAbbreviationMap.put("COMMONS", "CMNS");
		streetAbbreviationMap.put("CORNER", "COR");
		streetAbbreviationMap.put("CORNERS", "CORS");
		streetAbbreviationMap.put("COURSE", "CRSE");
		streetAbbreviationMap.put("COURT", "CT");
		streetAbbreviationMap.put("COURTS", "CTS");
		streetAbbreviationMap.put("COVE", "CV");
		streetAbbreviationMap.put("COVES", "CVS");
		streetAbbreviationMap.put("CREEK", "CRK");
		streetAbbreviationMap.put("CRESCENT", "CRES");
		streetAbbreviationMap.put("CRSENT", "CRES");
		streetAbbreviationMap.put("CRSNT", "CRES");
		streetAbbreviationMap.put("CREST", "CRST");
		streetAbbreviationMap.put("CROSSING", "XING");
		streetAbbreviationMap.put("CRSSNG", "XING");
		streetAbbreviationMap.put("CROSSROAD", "XRD");
		streetAbbreviationMap.put("CROSSROADS", "XRDS");
		streetAbbreviationMap.put("CURVE", "CURV");
		streetAbbreviationMap.put("DALE", "DL");
		streetAbbreviationMap.put("DAM", "DM");
		streetAbbreviationMap.put("DIVIDE", "DV");
		streetAbbreviationMap.put("DIV", "DV");
		streetAbbreviationMap.put("DIVIDE", "DV");
		streetAbbreviationMap.put("DVD", "DV");
		streetAbbreviationMap.put("DRIVE", "DR");
		streetAbbreviationMap.put("DRIV", "DR");
		streetAbbreviationMap.put("DRV", "DR");
		streetAbbreviationMap.put("DRIVES", "DRS");
		streetAbbreviationMap.put("ESTATE", "EST");
		streetAbbreviationMap.put("ESTATES", "ESTS");
		streetAbbreviationMap.put("EXPRESSWAY", "EXPY");
		streetAbbreviationMap.put("EXP", "EXPY");
		streetAbbreviationMap.put("EXPR", "EXPY");
		streetAbbreviationMap.put("EXPRESS", "EXPY");
		streetAbbreviationMap.put("EXPW", "EXPY");
		streetAbbreviationMap.put("EXTENSION", "EXT");
		streetAbbreviationMap.put("EXTN", "EXT");
		streetAbbreviationMap.put("EXTNSN", "EXT");
		streetAbbreviationMap.put("EXTENSIONS", "EXTS");
		streetAbbreviationMap.put("FALL", "FALL");
		streetAbbreviationMap.put("FALLS", "FLS");
		streetAbbreviationMap.put("FERRY", "FRY");
		streetAbbreviationMap.put("FRRY", "FRY");
		streetAbbreviationMap.put("FIELD", "FLD");
		streetAbbreviationMap.put("FIELDS", "FLDS");
		streetAbbreviationMap.put("FLAT", "FLT");
		streetAbbreviationMap.put("FLATS", "FLTS");
		streetAbbreviationMap.put("FORD", "FRD");
		streetAbbreviationMap.put("FORDS", "FRDS");
		streetAbbreviationMap.put("FOREST", "FRST");
		streetAbbreviationMap.put("FORESTS", "FRST");
		streetAbbreviationMap.put("FORGE", "FRG");
		streetAbbreviationMap.put("FORG", "FRG");
		streetAbbreviationMap.put("FORGES", "FRGS");
		streetAbbreviationMap.put("FORK", "FRK");
		streetAbbreviationMap.put("FORKS", "FRKS");
		streetAbbreviationMap.put("FORT", "FT");
		streetAbbreviationMap.put("FRT", "FT");
		streetAbbreviationMap.put("FREEWAY", "FWY");
		streetAbbreviationMap.put("FREEWY", "FWY");
		streetAbbreviationMap.put("FRWAY", "FWY");
		streetAbbreviationMap.put("FRWY", "FWY");
		streetAbbreviationMap.put("GARDEN", "GDN");
		streetAbbreviationMap.put("GARDN", "GDN");
		streetAbbreviationMap.put("GRDEN", "GDN");
		streetAbbreviationMap.put("GRDN", "GDN");
		streetAbbreviationMap.put("GARDENS", "GDNS");
		streetAbbreviationMap.put("GRDNS", "GDNS");
		streetAbbreviationMap.put("GATEWAY", "GTWY");
		streetAbbreviationMap.put("GATEWY", "GTWY");
		streetAbbreviationMap.put("GATWAY", "GTWY");
		streetAbbreviationMap.put("GTWAY", "GTWY");
		streetAbbreviationMap.put("GLEN", "GLN");
		streetAbbreviationMap.put("GLENS", "GLNS");
		streetAbbreviationMap.put("GREEN", "GRN");
		streetAbbreviationMap.put("GREENS", "GRNS");
		streetAbbreviationMap.put("GROVE", "GRV");
		streetAbbreviationMap.put("GROV", "GRV");
		streetAbbreviationMap.put("GROVES", "GRVS");
		streetAbbreviationMap.put("HARBOR", "HBR");
		streetAbbreviationMap.put("HARB", "HBR");
		streetAbbreviationMap.put("HARBR", "HBR");
		streetAbbreviationMap.put("HRBOR", "HBR");
		streetAbbreviationMap.put("HARBORS", "HBRS");
		streetAbbreviationMap.put("HAVEN", "HVN");
		streetAbbreviationMap.put("HEIGHTS", "HTS");
		streetAbbreviationMap.put("HT", "HTS");
		streetAbbreviationMap.put("HIGHWAY", "HWY");
		streetAbbreviationMap.put("HIGHWY", "HWY");
		streetAbbreviationMap.put("HIWAY", "HWY");
		streetAbbreviationMap.put("HIWY", "HWY");
		streetAbbreviationMap.put("HWAY", "HWY");
		streetAbbreviationMap.put("HILL", "HL");
		streetAbbreviationMap.put("HILLS", "HLS");
		streetAbbreviationMap.put("HOLLOW", "HOLW");
		streetAbbreviationMap.put("HLLW", "HOLW");
		streetAbbreviationMap.put("HOLLOWS", "HOLW");
		streetAbbreviationMap.put("HOLWS", "HOLW");
		streetAbbreviationMap.put("INLET", "INLT");
		streetAbbreviationMap.put("ISLAND", "IS");
		streetAbbreviationMap.put("ISLND", "IS");
		streetAbbreviationMap.put("ISLANDS", "ISS");
		streetAbbreviationMap.put("ISLNDS", "ISS");
		streetAbbreviationMap.put("ISLES", "ISLE");
		streetAbbreviationMap.put("JUNCTION", "JCT");
		streetAbbreviationMap.put("JCTION", "JCT");
		streetAbbreviationMap.put("JCTN", "JCT");
		streetAbbreviationMap.put("JUNCTN", "JCT");
		streetAbbreviationMap.put("JUNCTON", "JCT");
		streetAbbreviationMap.put("JUNCTIONS", "JCTS");
		streetAbbreviationMap.put("JCTNS", "JCTS");
		streetAbbreviationMap.put("KEY", "KY");
		streetAbbreviationMap.put("KEYS", "KYS");
		streetAbbreviationMap.put("KNOLL", "KNL");
		streetAbbreviationMap.put("KNOL", "KNL");
		streetAbbreviationMap.put("KNOLLS", "KNLS");
		streetAbbreviationMap.put("LAKE", "LK");
		streetAbbreviationMap.put("LAKES", "LKS");
		streetAbbreviationMap.put("LAND", "LAND");
		streetAbbreviationMap.put("LANDING", "LNDG");
		streetAbbreviationMap.put("LNDNG", "LNDG");
		streetAbbreviationMap.put("LANE", "LN");
		streetAbbreviationMap.put("LIGHT", "LGT");
		streetAbbreviationMap.put("LIGHTS", "LGTS");
		streetAbbreviationMap.put("LOAF", "LF");
		streetAbbreviationMap.put("LOCK", "LCK");
		streetAbbreviationMap.put("LOCKS", "LCKS");
		streetAbbreviationMap.put("LODGE", "LDG");
		streetAbbreviationMap.put("LDGE", "LDG");
		streetAbbreviationMap.put("LODG", "LDG");
		streetAbbreviationMap.put("LOOPS", "LOOP");
		streetAbbreviationMap.put("MALL", "MALL");
		streetAbbreviationMap.put("MANOR", "MNR");
		streetAbbreviationMap.put("MANORS", "MNRS");
		streetAbbreviationMap.put("MEADOW", "MDW");
		streetAbbreviationMap.put("MEADOWS", "MDWS");
		streetAbbreviationMap.put("MDW", "MDWS");
		streetAbbreviationMap.put("MEDOWS", "MDWS");
		streetAbbreviationMap.put("MEWS", "MEWS");
		streetAbbreviationMap.put("MILL", "ML");
		streetAbbreviationMap.put("MILLS", "MLS");
		streetAbbreviationMap.put("MISSION", "MSN");
		streetAbbreviationMap.put("MISSN", "MSN");
		streetAbbreviationMap.put("MSSN", "MSN");
		streetAbbreviationMap.put("MOTORWAY", "MTWY");
		streetAbbreviationMap.put("MOUNT", "MT");
		streetAbbreviationMap.put("MNT", "MT");
		streetAbbreviationMap.put("MOUNTAIN", "MTN");
		streetAbbreviationMap.put("MNTAIN", "MTN");
		streetAbbreviationMap.put("MNTN", "MTN");
		streetAbbreviationMap.put("MOUNTIN", "MTN");
		streetAbbreviationMap.put("MTIN", "MTN");
		streetAbbreviationMap.put("MOUNTAINS", "MTNS");
		streetAbbreviationMap.put("MNTNS", "MTNS");
		streetAbbreviationMap.put("NECK", "NCK");
		streetAbbreviationMap.put("ORCHARD", "ORCH");
		streetAbbreviationMap.put("ORCHRD", "ORCH");
		streetAbbreviationMap.put("OVL", "OVAL");
		streetAbbreviationMap.put("OVERPASS", "OPAS");
		streetAbbreviationMap.put("PRK", "PARK");
		streetAbbreviationMap.put("PARKS", "PARK");
		streetAbbreviationMap.put("PARKWAY", "PKWY");
		streetAbbreviationMap.put("PARKWY", "PKWY");
		streetAbbreviationMap.put("PKWAY", "PKWY");
		streetAbbreviationMap.put("PKY", "PKWY");
		streetAbbreviationMap.put("PARKWAYS", "PKWY");
		streetAbbreviationMap.put("PKWYS", "PKWY");
		streetAbbreviationMap.put("PASS", "PASS");
		streetAbbreviationMap.put("PASSAGE", "PSGE");
		streetAbbreviationMap.put("PATHS", "PATH");
		streetAbbreviationMap.put("PIKES", "PIKE");
		streetAbbreviationMap.put("PINE", "PNE");
		streetAbbreviationMap.put("PINES", "PNES");
		streetAbbreviationMap.put("PLACE", "PL");
		streetAbbreviationMap.put("PLAIN", "PLN");
		streetAbbreviationMap.put("PLAINS", "PLNS");
		streetAbbreviationMap.put("PLAZA", "PLZ");
		streetAbbreviationMap.put("PLZA", "PLZ");
		streetAbbreviationMap.put("POINT", "PT");
		streetAbbreviationMap.put("POINTS", "PTS");
		streetAbbreviationMap.put("PORT", "PRT");
		streetAbbreviationMap.put("PORTS", "PRTS");
		streetAbbreviationMap.put("PRAIRIE", "PR");
		streetAbbreviationMap.put("PRR", "PR");
		streetAbbreviationMap.put("RADIAL", "RADL");
		streetAbbreviationMap.put("RAD", "RADL");
		streetAbbreviationMap.put("RADIEL", "RADL");
		streetAbbreviationMap.put("RADL", "RADL");
		streetAbbreviationMap.put("RAMP", "RAMP");
		streetAbbreviationMap.put("RANCH", "RNCH");
		streetAbbreviationMap.put("RANCHES", "RNCH");
		streetAbbreviationMap.put("RNCHS", "RNCH");
		streetAbbreviationMap.put("RAPID", "RPD");
		streetAbbreviationMap.put("RAPIDS", "RPDS");
		streetAbbreviationMap.put("REST", "RST");
		streetAbbreviationMap.put("RIDGE", "RDG");
		streetAbbreviationMap.put("RDGE", "RDG");
		streetAbbreviationMap.put("RIDGES", "RDGS");
		streetAbbreviationMap.put("RIVER", "RIV");
		streetAbbreviationMap.put("RVR", "RIV");
		streetAbbreviationMap.put("RIVR", "RIV");
		streetAbbreviationMap.put("ROAD", "RD");
		streetAbbreviationMap.put("ROADS", "RDS");
		streetAbbreviationMap.put("ROUTE", "RTE");
		streetAbbreviationMap.put("ROW", "ROW");
		streetAbbreviationMap.put("RUE", "RUE");
		streetAbbreviationMap.put("RUN", "RUN");
		streetAbbreviationMap.put("SHOAL", "SHL");
		streetAbbreviationMap.put("SHOALS", "SHLS");
		streetAbbreviationMap.put("SHORE", "SHR");
		streetAbbreviationMap.put("SHOAR", "SHR");
		streetAbbreviationMap.put("SHORES", "SHRS");
		streetAbbreviationMap.put("SHOARS", "SHRS");
		streetAbbreviationMap.put("SKYWAY", "SKWY");
		streetAbbreviationMap.put("SPNG", "SPG");
		streetAbbreviationMap.put("SPRING", "SPG");
		streetAbbreviationMap.put("SPRNG", "SPG");
		streetAbbreviationMap.put("SPNGS", "SPGS");
		streetAbbreviationMap.put("SPRINGS", "SPGS");
		streetAbbreviationMap.put("SPRNGS", "SPGS");
		streetAbbreviationMap.put("SPUR", "SPUR");
		streetAbbreviationMap.put("SPURS", "SPUR");
		streetAbbreviationMap.put("SQR", "SQ");
		streetAbbreviationMap.put("SQRE", "SQ");
		streetAbbreviationMap.put("SQU", "SQ");
		streetAbbreviationMap.put("SQUARE", "SQ");
		streetAbbreviationMap.put("SQRS", "SQS");
		streetAbbreviationMap.put("SQUARES", "SQS");
		streetAbbreviationMap.put("STATION", "STA");
		streetAbbreviationMap.put("STATN", "STA");
		streetAbbreviationMap.put("STN", "STA");
		streetAbbreviationMap.put("STRAV", "STRA");
		streetAbbreviationMap.put("STRAVEN", "STRA");
		streetAbbreviationMap.put("STRAVENUE", "STRA");
		streetAbbreviationMap.put("STRAVN", "STRA");
		streetAbbreviationMap.put("STRVN", "STRA");
		streetAbbreviationMap.put("STRVNUE", "STRA");
		streetAbbreviationMap.put("STREAM", "STRM");
		streetAbbreviationMap.put("STREME", "STRM");
		streetAbbreviationMap.put("STREET", "ST");
		streetAbbreviationMap.put("STRT", "ST");
		streetAbbreviationMap.put("STR", "ST");
		streetAbbreviationMap.put("STREETS", "STS");
		streetAbbreviationMap.put("SUMIT", "SMT");
		streetAbbreviationMap.put("SUMITT", "SMT");
		streetAbbreviationMap.put("SUMMIT", "SMT");
		streetAbbreviationMap.put("TERR", "TER");
		streetAbbreviationMap.put("TERRACE", "TER");
		streetAbbreviationMap.put("THROUGHWAY", "TRWY");
		streetAbbreviationMap.put("TRACE", "TRCE");
		streetAbbreviationMap.put("TRACES", "TRCE");
		streetAbbreviationMap.put("TRCE", "TRCE");
		streetAbbreviationMap.put("TRACK", "TRAK");
		streetAbbreviationMap.put("TRACKS", "TRAK");
		streetAbbreviationMap.put("TRK", "TRAK");
		streetAbbreviationMap.put("TRKS", "TRAK");
		streetAbbreviationMap.put("TRAFFICWAY", "TRFY");
		streetAbbreviationMap.put("TRAIL", "TRL");
		streetAbbreviationMap.put("TRAILS", "TRL");
		streetAbbreviationMap.put("TRLS", "TRL");
		streetAbbreviationMap.put("TRAILER", "TRLR");
		streetAbbreviationMap.put("TRLRS", "TRLR");
		streetAbbreviationMap.put("TUNNEL", "TUNL");
		streetAbbreviationMap.put("TUNEL", "TUNL");
		streetAbbreviationMap.put("TUNLS", "TUNL");
		streetAbbreviationMap.put("TUNNELS", "TUNL");
		streetAbbreviationMap.put("TUNNL", "TUNL");
		streetAbbreviationMap.put("TURNPIKE", "TPKE");
		streetAbbreviationMap.put("TRNPK", "TPKE");
		streetAbbreviationMap.put("TURNPK", "TPKE");
		streetAbbreviationMap.put("UNDERPASS", "UPAS");
		streetAbbreviationMap.put("UNION", "UN");
		streetAbbreviationMap.put("UNIONS", "UNS");
		streetAbbreviationMap.put("VALLEY", "VLY");
		streetAbbreviationMap.put("VALLY", "VLY");
		streetAbbreviationMap.put("VLLY", "VLY");
		streetAbbreviationMap.put("VALLEYS", "VLYS");
		streetAbbreviationMap.put("VIADUCT", "VIA");
		streetAbbreviationMap.put("VDCT", "VIA");
		streetAbbreviationMap.put("VIADCT", "VIA");
		streetAbbreviationMap.put("VIEW", "VW");
		streetAbbreviationMap.put("VIEWS", "VWS");
		streetAbbreviationMap.put("VILL", "VLG");
		streetAbbreviationMap.put("VILLAG", "VLG");
		streetAbbreviationMap.put("VILLAGE", "VLG");
		streetAbbreviationMap.put("VILLG", "VLG");
		streetAbbreviationMap.put("VILLIAGE", "VLG");
		streetAbbreviationMap.put("VILLAGES", "VLGS");
		streetAbbreviationMap.put("VILLE", "VL");
		streetAbbreviationMap.put("VIST", "VIS");
		streetAbbreviationMap.put("VISTA", "VIS");
		streetAbbreviationMap.put("VST", "VIS");
		streetAbbreviationMap.put("VSTA", "VIS");
		streetAbbreviationMap.put("WALK", "WALK");
		streetAbbreviationMap.put("WALKS", "WALK");
		streetAbbreviationMap.put("WALL", "WALL");
		streetAbbreviationMap.put("WY", "WAY");
		streetAbbreviationMap.put("WAYS", "WAYS");
		streetAbbreviationMap.put("WELL", "WL");
		streetAbbreviationMap.put("WELLS", "WLS");

		streetDirectionMap = new HashMap<String, String>();
		streetDirectionMap.put("NORTH", "N");
		streetDirectionMap.put("SOUTH", "S");
		streetDirectionMap.put("EAST", "E");
		streetDirectionMap.put("WEST", "W");
		streetDirectionMap.put("NORTHEAST", "NE");
		streetDirectionMap.put("NORTHWEST", "NW");
		streetDirectionMap.put("SOUTHEAST", "SE");
		streetDirectionMap.put("SOUTHWEST", "SW");
		
		loadStateLookUp();
		loadCategory();
	}

	public String standardizeAddressLine1(String s) {
		if (streetAbbreviationMap.get(s.toUpperCase()) != null) {
			return streetAbbreviationMap.get(s.toUpperCase());
		}
		if (streetDirectionMap.get(s.toUpperCase()) != null) {
			return streetDirectionMap.get(s.toUpperCase());
		}
		return null;
	}

	public void setCategoryDao(CategoryDao categoryDao) {
		this.categoryDao = categoryDao;
	}

	public Category getCategoryByName(String name) {
		if(categoryMap == null) loadCategory();
		return categoryMap.get(name);
	}

	public List<Category> getAllLeafCatogories() {
		if(leafCategories == null) loadCategory();
		return leafCategories;
	}

	public List<Category> getCategoriesByLevel(int level) {
		return categoryDao.findAllByLevel(level);
	}

	public String getStateNameByStateFp(String stateFp) {
		if(stateFipsToNameMap == null) loadStateLookUp();
		return stateFipsToNameMap.get(stateFp);
	}

	public String getStateFPByStateName(String stateName) {
		if(stateNameToFipsMap == null) loadStateLookUp();
		return stateNameToFipsMap.get(stateName);
	}

	private void loadCategory() {
		synchronized (categoryLock) {
			if (categoryMap == null) {
				categoryMap = new HashMap<String, Category>();
				leafCategories = new ArrayList<Category>();
				List<Category> categories = categoryDao.findAll();
				for (Category category : categories) {
					categoryMap.put(category.getName(), category);
					if (category.getChildren() == null || category.getChildren().size() == 0) {
						leafCategories.add(category);
					}
				}
			}
		}
	}

	private void loadStateLookUp() {
		synchronized (stateLock) {
			if (stateFipsToNameMap == null) {
				stateFipsToNameMap = new HashMap<String, String>();
			}
			if (stateNameToFipsMap == null) {
				stateNameToFipsMap = new HashMap<String, String>();
			}
			List<StateLookUp> stateList = stateLookUpDao.findAll();
			for (StateLookUp slu : stateList) {
				stateFipsToNameMap.put(slu.getStateFP(), slu.getAbbrev());
				stateNameToFipsMap.put(slu.getAbbrev(), slu.getStateFP());
				stateNameToFipsMap.put(slu.getName(), slu.getStateFP());
			}
		}
	}
}
